package com.shiguiwu.facade.starter.door.aspect;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.shiguiwu.facade.starter.door.anntation.DoDoor;
import com.shiguiwu.facade.starter.door.prop.FacadeProperties;
import com.shiguiwu.facade.starter.door.service.FacadeService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;

/**
 * @description: 门面拦截
 * @author: stone
 * @date: Created by 2021/8/29 11:52
 * @version: 1.0.0
 * @pakeage: com.shiguiwu.facade.starter.door.aspect
 */
@Aspect
public class DoorAspect {

    private Logger logger = LoggerFactory.getLogger(DoorAspect.class);

    private FacadeService facadeService;

    public DoorAspect(FacadeService facadeService) {
        this.facadeService = facadeService;
    }


    @Pointcut("@annotation(com.shiguiwu.facade.starter.door.anntation.DoDoor)")
    public void pointCut() {

    }


    @Around("pointCut()")
    public Object doRouter(ProceedingJoinPoint joinPoint) throws Throwable {
        //获取方法
        Method method = this.getMethod(joinPoint);
        //获取方法上的注解
        DoDoor doDoor = method.getAnnotation(DoDoor.class);
        //获取值
        String filedValue = this.getFiledValue(doDoor.key(), joinPoint.getArgs());
        logger.info("my door handler method：{} value：{}", method.getName(), filedValue);
        if (StrUtil.isBlank(filedValue)) {
            return joinPoint.proceed();
        }
        //获取配置内容
        String[] split = facadeService.split(",");
        for (String key : split) {
            if (filedValue.equals(key)) {
                return joinPoint.proceed();
            }
        }
        return this.returnObject(doDoor, method);
    }


    /**
     * 获取方法对象
     * @param joinPoint
     * @return
     * @throws Exception
     */
    private Method getMethod(ProceedingJoinPoint joinPoint) throws Exception {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        return this.getClass(joinPoint).getMethod(methodSignature.getName(), methodSignature.getParameterTypes());
    }

    /**
     * 获取class
     * @param joinPoint
     * @return
     */
    private Class<? extends Object> getClass(ProceedingJoinPoint joinPoint) {
        return joinPoint.getTarget().getClass();
    }


    /**
     * 获取返回对象
     * @param doDoor
     * @param method
     * @return
     * @throws Exception
     */
    private Object returnObject(DoDoor doDoor, Method method) throws Exception {
        Class<?> returnType = method.getReturnType();
        String returnJson = doDoor.returnJson();
        if (StrUtil.isBlank(returnJson)) {
            return returnType.newInstance();
        }
        return JSONUtil.toBean(returnJson, returnType);
    }


    /**
     * 通过字段名获取值
     * @param filed
     * @param args
     * @return
     */
    private String getFiledValue(String filed, Object[] args) {
        String filedValue = null;
        for (Object arg : args) {
            try {
                if (StrUtil.isBlank(filedValue)) {
                    filedValue =  BeanUtil.getFieldValue(arg, filed).toString();
                }
                else {
                    break;
                }
            } catch (Exception e) {
                if (args.length == 1) {
                    filedValue = args[0].toString();
                }
            }
        }
        return filedValue;
    }



}
